package scalab.core.component

import scala.collection.immutable.{Set, HashSet}

import scalab.core.dependencies.{HardDependency, SoftDependency}

/**
*	The fundamental difference with 
* a task is that a filter is not affected by dependencies. 
*	That is, the filter will be executed even if the resource 
*	of some hard dependency does not exist. Intuitivelly, a 
*	filter refines the set of dependencies it recieves. 
* Note that a filter does not necessarily reduce the set of 
* dependencies but can also mutate hard dependencies to soft ones (or vice versa) 
*	and even produce new dependencies. 
*/
trait Filter extends ExecutableComponent{

	def execute: Boolean

  //TODO
  //var fileDeps: HashMap<Task, FileDependency extends FileResource>
  def impose(path: String): Component = 
    submit(HardDependency(path))

	def impose(resource: Resource): Component = 
		impose(resource.getPath)

	def impose(paths: Iterable[String]): Component =
		submit(paths map {p => HardDependency(p)})

  def suggest(path: String): Component =
    submit(SoftDependency(path))

	def suggest(resource: Resource): Component = 
		suggest(resource.getPath)

	def suggest(paths: Iterable[String]): Component =
		submit(paths map {p => SoftDependency(p)})
		
	/*def transmit(dep: Dependency): Component = submit(dep)
	def transmit(deps: Iterable[Dependency]): Component = {
		submit(deps)
	}*/

	/*def forward(c: Component): Component = {
		fwd(c.out)
	}*/
	//implement freshComponentName to get unique names...

	/**
	* Executes this filter.
	*/
	private[core] def exec: Boolean = {
		//info("executes")

		//remove these two lines when filters cache is enabled
		//but leave it when NoCache is enabled...
		/*import scala.collection.immutable.TreeSet
		out.setDeps(TreeSet.empty(Dependency.dependency2ordered _))*/
		reset
		val res = execute
		//info("deps = " + productDependencies.mkString("\n", "\n", ""))
		res
	}

	//implement this!!!
	final def locallyUpToDate(products: Set[Resource]): Boolean = false

	//def returnValue: Boolean = true
	Filter.allFilters = Filter.allFilters + this
}

object Filter{
	
	private[core] var allFilters: Set[Filter] = HashSet.empty[Filter]
	def getAll: Set[Filter] = allFilters
}
